function scope(util) {
    var toString = 'toString';
    var valueOf = 'valueOf';
    var prototype = '.prototype';
    var __lookupGetter__ = '__lookupGetter__';

    // 判断是否非系统内置函数（必须在动态代码中定义，不能放在util中，避免util本身被整体重写并伪造toString）
    function isBuiltin(foo, name) {

        // 首先必须是函数
        if (typeof(foo) !== 'function') return -1;
        if (!(foo instanceof Function)) return -2;

        // 系统内置函数转字符串始终为：function foo() { [nativecode] }（不同引擎下空白格式可能不同）
        var body = foo + '';
        if (body.length > 100) return 1;
        if (body.replace(/\s/g, '') != 'function' + (name || foo.name) + '(){[nativecode]}') return 1;

        // foo.toString或valueOf方法，可能被重写来伪造返回字符串，所以要判断是否为默认函数
        if (foo.toString !== isBuiltin.toString) return 2;
        if (foo.valueOf !== isBuiltin.valueOf) return 3;

        // 内置函数访问caller属性会报异常，而自定义函数一定有值且不可修改（箭头函数除外）
        // 但箭头函数取不到函数自身this，无法区分是否为重写函数，因此可通过构造临时函数判断
        try {
            foo.caller;
            return 4;
        } catch (e) {
        }

        // Function函数还需加特殊判断
        if (foo === Function) {
            if (isBuiltin.constructor !== foo) return 5;
        }

        // TODO Array.length等内置属性也可能被重写
        return 0;
    }
    var lookupGetter = isBuiltin[__lookupGetter__];

    // 检验内置函数是否被重写（若有则抛出异常）
    // - @target 可为要检测的函数或方法主体，或一个批量列表：[[target, name, [method, ...], ...]
    // - @name 函数或主体名称（未填表示target为批量列表）
    // - @method 方法名称（以.开头表示getter属性，空表示target为要检测的函数）
    function checkBuiltin(target, name, method) {
        if (name) {
            var code = 9;
            if (method) {
                if (method.charAt(0) == '.') {
                    if (!lookupGetter.call(target, method.substr(1))) return;
                    throw 'Should not overwrite built-in property ' + name + method + '!';
                }
                if (!lookupGetter.call(target, method)) {
                    code = isBuiltin(target[method], method);
                    if (!code) return;
                }
                name += '.' + method;
            } else {
                code = isBuiltin(target, name);
                if (!code) return;
            }
            throw 'Should not overwrite built-in function ' + name + '()! [code ' + code + ']';
        }
        for (var i in target) {
            i = target[i];
            for (var j in i[2]) {
                checkBuiltin(i[0], i[1], i[2][j]);
            }
        }
    }

    // 检验所有用到的内置函数是否被重写，避免重写内置函数加断点攻击
    var checkList = [
        [Function, 'Function', ['']],
        [parseInt, 'parseInt', ['']],
        [escape, 'escape', ['']],
        [unescape, 'unescape', ['']],
        [encodeURIComponent, 'encodeURIComponent', ['']],
        [decodeURIComponent, 'decodeURIComponent', ['']],
        [String, 'String', [
            'fromCharCode',
        ]],
        [Date, 'Date', [
            'now',
        ]],
        [JSON, 'JSON', [
            'stringify',
        ]],
        [Math, 'Math', [
            'floor',
            'ceil',
            'random',
        ]],
        [0, 'Number' + prototype, [
            toString,
            valueOf,
        ]],
        ['', 'String' + prototype, [
            toString,
            valueOf,
            'charCodeAt',
            'charAt',
            'substr',
            'trim',
            'indexOf',
            'replace',
            'match',
        ]],
        [[], 'Array' + prototype, [
            toString,
            valueOf,
            'push',
            'pop',
            'concat',
            'slice',
            'join',
            '.length',
        ]],
        [{}, 'Object' + prototype, [
            toString,
            valueOf,
        ]],
        [isBuiltin, 'Function' + prototype, [
            toString,
            valueOf,
            __lookupGetter__,
            '.constructor',
            '.name',
        ]],
        [lookupGetter, 'Function' + prototype + '.' + __lookupGetter__, [
            'call',
        ]],
        [util, 'util', [
            toString,
            valueOf,
        ]],
    ];
    try {
        checkBuiltin(checkList);
    } catch (e) {
        return function () {
            return e + '';
        }
    }

    // 构造异常并检测时间，避免被任意异常断点攻击
    var now = Date.now();
    try {
        throw 0;
    } catch (e) {}
    if (Date.now() - now > 10) {
        return function () {
            return 'Should not pause on exceptions!';
        };
    }

    // 取工具函数
    var J$ = util();
    var aes = J$[0];
    var hex2json = J$[1];
    var md5 = aes.md5;

    // 初始化动态参数
    var key = "k@${key}".substr(2); // 动态HEX健（用于构造伪随机Json）
    var layers = "l@${layers}".substr(2); // 递归层数
    var compact = "${compact}"; // 是否兼容IE
    key = key.length < 32 ? md5(key) : key.substr(-1000);

    // 获取当前上下文代码，并剥离外层function定义
    var scope = arguments.callee + '';
    var pos = scope.indexOf('{');
    scope = scope.substr(pos + 1, scope.length - pos - 2).trim();
    // console.log(layers, '环境:', md5(util + ''), md5(scope));

    // 通过广义Json语法构造不确定的异常，避免被外部模拟逻辑攻击（因为异常堆栈无法模拟，且难以推算？）
    var json = hex2json(key, compact);
    // console.log(layers, '构造:', json);
    try {
        json = JSON.stringify(Function('a', 'return ' + json)(key));
        // console.log(layers, 'JSON:', json, md5(json));
        key += md5(util + scope + json).substr(json.length % 10);
    } catch (e) {
        var stack = '';
        if (!compact) { // 兼容IE时不使用堆栈信息
            // console.log(layers, '堆栈:', e.stack);
            stack = e.stack.match(/ <anonymous>:[0-9]+:[0-9]+/g);
            if (stack) {
                // 只保留列号且只留1~10项，因为不同浏览器的行号和断点定位可能不同，而Chrome只记录了10项
                stack = stack.slice(1, 10).join('').replace(/<anonymous>:[0-9]+/g, '');
            } else {
                stack = e.stack.match(/ Function:[0-9]+:[0-9]+/g); // 兼容Firefox浏览器
                stack = stack.slice(1, 10).join('').replace(/Function:[0-9]+/g, '');
            }
            // console.log(layers, '异常:', e, stack);
        }
        key = md5(util + scope + json + stack).substr(json.length % 10);
    }
    // console.log(layers, '秘钥:', key);

    return function(code) {
        if (typeof(code) != 'string') {
            return 'Input code is not a string!';
        }

        // 构造动态代码，并递归调用
        if (--layers > 0) {
            scope = scope.replace(/"k@[^"]*"/, '"k@' + key + '"');
            scope = scope.replace(/"l@[^"]*"/, '"l@' + layers + '"');
            return Function('t', scope)(util)(code);
        }

        // 首字符为\n表示源码，进行加密，否则进行解密后执行
        try {
            var source = code.charCodeAt(0) == 10;
            if (source) {
                return aes.enc(code, key);
            }
            code = aes.dec(code, key);
            if (md5(code) != "${key}") { // 校验源码MD5值，避免被构造源码攻击
                return 'Source code md5 mismatch!';
            }
            return Function('J$', code)({ // 将工具函数打包传入复用（比如用于检测更多内置函数是否被重写）
                checkBuiltin: checkBuiltin,
                aes: aes,
                md5: md5,
            });
        } catch (e) {
            return e + '';
        }
    }
}
